/*
 * Created on 14/08/2005
 *
 */
package guru.mercurio.core.delivery;

import guru.mercurio.common.AbsoluteApplicationAddress;
import guru.mercurio.common.RelativeApplicationAddress;
import guru.mercurio.data.ChannelDataManager;
import guru.mercurio.data.DataManager;
import guru.merlin.core.CantHandException;
import guru.merlin.core.Envelope;
import guru.merlin.core.EnvelopeCantHandException;
import guru.merlin.core.InfrastructureCantHandException;
import guru.merlin.core.RuntimeConfigurationCantHandException;

import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;

 
public class PreDispatchProcessor {
    Logger logger=Logger.getLogger(PreDispatchProcessor.class);
    Set multiplexedChannels; 
    DataManager dm;
    ChannelDataManager cdm;
    
    public PreDispatchProcessor(DataManager dm) throws Exception{
        this.dm=dm;
        cdm=new ChannelDataManager(dm);
        multiplexedChannels=loadMultiplexedChannels();

    }
    
    private Set loadMultiplexedChannels() {
        Set map = new HashSet();
        map.add("22625");
        return (map);
    }
        
    public AbsoluteApplicationAddress preProcess(Envelope envelope) throws CantHandException {
        //String msg = "";
        String text;
        String word;
        String rest;
        int pos;
        AbsoluteApplicationAddress[] apps;
        AbsoluteApplicationAddress app;

        
        if(!(envelope.getDestination() instanceof RelativeApplicationAddress)){
            throw new EnvelopeCantHandException("Can't preprocess an Envelope with a destination different from ApplicationAddress");
        }
        
        String channelId=envelope.getDestination().getPort();
        
        
        if (multiplexedChannels.contains(channelId)) {
            logger.debug("Es un canal multiplexado");
            if ((pos = (text = envelope.getContent().toString()).indexOf(" ")) != -1) {
                word = text.substring(0, pos);
                rest = text.substring(pos);
            } else {
                word = text;
                rest = "";
            }

            try{
            	apps = cdm.getApplicationBySubChannel(channelId, word);
            }
            catch(Exception e){
            	throw new InfrastructureCantHandException(""+e); 
            }
            
            if (apps.length == 1) {                
                logger.debug("Se encontr una aplicacin para subcanal '" + word + "@" + channelId + "'");

                app = apps[0];
                
                envelope.setContent(rest.trim());
                return app;
                
            } else if (apps.length == 0) {                
                logger.debug("No se encontr una aplicacin para subcanal '" + word + "@" + channelId + "', intentando bsqueda de app default para canal multiplexado '" + channelId + "'");
                
                try{
                	apps = cdm.getApplicationByChannel(channelId);
                }
                catch(Exception e){
                	throw new InfrastructureCantHandException(""+e); 
                }

                if (apps.length == 1) {
                    
                    logger.debug("Se encontr app default para canal multiplexado '" + channelId + "'");

                    app = apps[0];

                    //envelope.setMetaDestination(app);
                    return app;
                } else {
                    throw new RuntimeConfigurationCantHandException("No se encontr app default para canal multiplexado '" + channelId + "'");
                }
            } else {
                throw new RuntimeConfigurationCantHandException("Se encontaron muchas aplicaciones para un mismo subcanal: no se cul utilizar.");
            }

        } else {
            logger.debug("Es un canal NO multiplexado");
            try{
            	apps = cdm.getApplicationByChannel(channelId);
            }
            catch(Exception e){
            	throw new InfrastructureCantHandException(""+e); 
            }

            if (apps.length == 1) {
                logger.debug("Se encontro una aplicacion para canal '" + channelId + "', del pasaporte '" + apps[0].getPassport() + "'");
 
                app = apps[0];
                
                //envelope.setMetaDestination(app);
                return app;
            } else {
                throw new RuntimeConfigurationCantHandException("No se encontro una aplicacion para canal '" + channelId + "'");
            }
        }

    }

    
    
}
